<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <button onclick="clickMe()">点我</button>
    <script>
        // 写一个最多能并发执行n个promise的队列
        // 异步请求队列
        const queue = []
        // 用来模拟不同的返回值
        let index = 0
        // 标志是否正在处理队列中的请求
        let running = false
        // 异步请求并发数限制
        const syncCount = 2

        // 使用setTimeout模拟异步请求
        function request(index) {
            return new Promise(function (resolve) {
                setTimeout(() => {
                    resolve(index)
                }, 1000)
            })
        }

        // 连续点击，触发异步请求，加入任务队列
        function clickMe() {
            addQueue(() => request(index++))
        }

        // 当队列中任务数大于0时，开始处理队列中的任务
        function addQueue(item) {
            queue.push(item)
            if (queue.length > 0 && !running) {
                running = true
                processMulti(syncCount)
            }
        }

        // 使用Promise.all来保证并发数限制
        function processMulti(count) {
            const arr = []
            for (let i = 0; i < count; i++) {
                const item = queue.shift()
                item && arr.push(item())
            }
            if (arr.length > 0) {
                Promise.all(arr).then(res => {
                    console.log(res)
                    processMulti(count)
                })
            } else {
                running = false
            }
        }


    </script>
</body>

</html>